﻿
using System.Text.RegularExpressions;

namespace S3.WMDSLEditor.Xslt
{
    public static class XsltTransform
    {
        public static bool CheckForKnownXsltTags(string text)
        {
            Regex emailregex = new Regex(KnownXslTagsPattern);

            Match m = emailregex.Match(text);

            if(m.Success)
            {
                return true;
            }

            return false;
        }

        // Matches xsl or xml tags or html w/namespace:qualifiers
        private static string XslTagPattern
        {
            get
            {
                //XmlTag Regex modified from html tag version

                //changed "<tagname>\w+" to "<tagname>\w+(:\w+)?"
                //similar change in attribute name; both to allow namespace qualifiers

                //some html-based safety nets could be dumped for xml use but

                //<(?<endTag>/)?(?<tagname>\w+(:\w+)?)((\s+(?<attName>\w+(:\w+)?)(\s*=\s*(?:"(?<attVal>[^"]*)"|'(?<attVal>[^']*)'|(?<attVal>[^'">\s]+)))?)+\s*|\s*)(?<completeTag>/)?>

                return
                    @"<"
                    + @"(?<endTag>/)?"    //Captures the / if this is an end tag.
                    + @"(?<tagname>\w+(:\w+)?)"    //Captures TagName (changed)
                    + @"("                //Groups tag contents
                    + @"(\s+"            //Groups attributes
                    + @"(?<attName>\w+(:\w+)?)"  //Attribute name
                    + @"("                //groups =value portion.
                    + @"\s*=\s*"            // = 
                    + @"(?:"        //Groups attribute "value" portion.
                    + @"""(?<attVal>[^""]*)"""    // attVal='double quoted'
                    + @"|'(?<attVal>[^']*)'"        // attVal='single quoted'
                    + @"|(?<attVal>[^'"">\s]+)"    // attVal=urlnospaces
                    + @")"
                    + @")?"        //end optional att value portion.
                    + @")+\s*"        //One or more attribute pairs
                    + @"|\s*"            //Some white space.
                    + @")"
                    + @"(?<completeTag>/)?>"; //Captures the "/" if this is a complete tag.
            }
        }

        // Matches all currently known xsl tags
        private static string KnownXslTagsPattern
        {
            get
            {
                const string pattern = "<(?<endTag>/)?(?<tagname>(xsl:apply-imports|xsl:apply-templates|xsl:attribute|xsl:attribute-set|xsl:call-template|xsl:choose|xsl:comment|xsl:copy|xsl:copy-of|xsl:decimal-format|xsl:document|xsl:element|xsl:fallback|xsl:for-each|xsl:if|xsl:import|xsl:include|xsl:key|xsl:message|xsl:namespace-alias|xsl:number|xsl:otherwise|xsl:output|xsl:param|xsl:preserve-space|xsl:processing-instruction|xsl:script|xsl:sort|xsl:strip-space|xsl:stylesheet|xsl:template|xsl:text|xsl:transform|xsl:value-of|xsl:variable|xsl:when|xsl:with-param)?)((\\s+(?<attName>\\w+(:\\w+)?)(\\s*=\\s*(?:\"(?<attVal>[^\"]*)\"|'(?<attVal>[^']*)'|(?<attVal>[^'\">\\s]+)))?)+\\s*|\\s*)(?<completeTag>/)?>";
                return pattern;
            }
        }

        // Matches xsl functions
        private static string KnownXslFunctionsPattern
        {
            get
            {
                //assume context is already in that of an attribute value
                //so no need to include tags or attribute patterns just simple list
                //just match func( or func (
                //hope you don't mind scrolling b/c i'm too lazy to format
                return @"boolean(\s)?(?:\()|ceil(\s)?(?:\()|ceiling(\s)?(?:\()|concat(\s)?(?:\()|contains(\s)?(?:\()|count(\s)?(?:\()|current(\s)?(?:\()|document(\s)?(?:\()|element-available(\s)?(?:\()|entity-uri(\s)?(?:\()|false(\s)?(?:\()|floor(\s)?(?:\()|format-number(\s)?(?:\()|function-available(\s)?(?:\()|generate-id(\s)?(?:\()|getLast(\s)?(?:\()|getRemainder(\s)?(?:\()|id(\s)?(?:\()|init(\s)?(?:\()|key(\s)?(?:\()|lang(\s)?(?:\()|last(\s)?(?:\()|local-name(\s)?(?:\()|name(\s)?(?:\()|namespace-uri(\s)?(?:\()|normalize-space(\s)?(?:\()|not(\s)?(?:\()|number(\s)?(?:\()|position(\s)?(?:\()|refresh(\s)?(?:\()|round(\s)?(?:\()|starts-with(\s)?(?:\()|string(\s)?(?:\()|string-length(\s)?(?:\()|substring(\s)?(?:\()|substring-after(\s)?(?:\()|substring-before(\s)?(?:\()|sum(\s)?(?:\()|system-property(\s)?(?:\()|translate(\s)?(?:\()|true(\s)?(?:\()|unparsed-entity-uri(\s)?(?:\()";
            }
        }

        // Returns pattern for attribute name="value" pairs
        private static string AttributeNameValuePattern
        {
            get
            {
                return "(?<1>\\w+)\\s*=\\s*(?:\"(?<2>[^\"]*)\"|(?<2>\\S+))";
            }
        }
    }
}
